﻿using Bit.Art.Core.Extensions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Bit.Art.Core.Models
{
    /// <summary>
    /// 用户账户余额
    /// </summary>
    public class AccountBalance : IComparable, IComparable<AccountBalance>, IFixByteSerializable
    {
        private const int CUSTOM_SERIALIZE_SIZE = 40;

        public AccountBalance() { }

        public AccountBalance(Guid id, uint accountId, string currency, decimal balance, decimal pending)
        {
            Id = id;
            AccountId = accountId;
            Currency = currency;
            Balance = balance;
            Pending = pending;
        }

        /// <summary>
        /// 主键
        /// </summary>
        public Guid Id { get; set; }

        /// <summary>
        /// 用户的Id
        /// </summary>
        public uint AccountId { get; set; }

        /// <summary>
        /// 数字币
        /// </summary>
        public string Currency { get; set; }

        /// <summary>
        /// 币种地址
        /// </summary>
        public string Address { get; set; }

        /// <summary>
        /// 币种存币所需的额外Tag
        /// </summary>
        public string Tag { get; set; }

        /// <summary>
        /// 总余额
        /// </summary>
        public decimal Balance { get; set; }

        /// <summary>
        /// 可用余额
        /// </summary>
        public decimal Available { get { return Balance - Pending; } }

        /// <summary>
        /// 挂单余额
        /// </summary>
        public decimal Pending { get; set; }

        /// <summary>
        /// 序列化后的字节数组大小，值是40
        /// </summary>
        public int ByteSize => CUSTOM_SERIALIZE_SIZE;

        #region ISerializable成员
        public int CompareTo(object obj)
        {
            if (obj == null)
            {
                return 1;
            }
            else if (obj != null && obj is string)
            {
                return Currency.CompareTo((string)obj);
            }
            else
            {
                return CompareTo((AccountBalance)obj);
            }
        }

        public int CompareTo(AccountBalance other)
        {
            if (other == null)
                return 1;
            else
                return Currency.CompareTo(other.Currency);
        }
        #endregion

        /// <summary>
        /// 将一个用户余额序列化成字节数组，采用自定义的序列化以节省空间
        /// </summary>
        /// <param name="item">要序列化的订单</param>
        /// <returns>序列化后的字节</returns>
        /// <remarks>
        /// 格式：
        /// 000 - 007: Currency
        /// 008 - 023: Balance
        /// 024 - 039: Pending
        /// </remarks>
        public byte[] ToFixedBytes()
        {
            var bytes = new byte[CUSTOM_SERIALIZE_SIZE];

            byte[] serializedBytes;
            // Currency
            if (!string.IsNullOrWhiteSpace(Currency))
            {
                serializedBytes = System.Text.Encoding.ASCII.GetBytes(Currency);
                Array.Copy(serializedBytes, 0, bytes, 0, Math.Min(8, serializedBytes.Length));
            }

            // Balance
            Utility.Serialize(Balance, bytes, 8);
            // Pending
            Utility.Serialize(Pending, bytes, 24);

            return bytes;
        }

        public static AccountBalance FromBytes(byte[] bytes)
        {
            var item = new AccountBalance();
            item.InitFrom(bytes);
            return item;
        }

        public void InitFrom(byte[] bytes)
        {
            // Currency
            var acctLen = 0;
            for (var i = 0; i < 8; ++i, ++acctLen)
            {
                if (bytes[i] == 0)
                    break;
            }
            var serializedBytes = new byte[acctLen];
            Array.Copy(bytes, 0, serializedBytes, 0, acctLen);
            Currency = Encoding.ASCII.GetString(serializedBytes);

            // Balance
            Balance = Utility.DecimalFromBytes(bytes, 8);
            // Pending
            Pending = Utility.DecimalFromBytes(bytes, 24);
        }
    }
}
